-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--          http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
local validate = require 'mc.validate'
local utils = require 'mc.utils'
local mdb = require 'mc.mdb'

local EfficiencyCurve = {}

---@class EfficiencyCurve.PowerLevel
---@field PowerLevel string
local TPowerLevel = {}
TPowerLevel.__index = TPowerLevel
TPowerLevel.group = {}

local function TPowerLevel_from_obj(obj)
    return setmetatable(obj, TPowerLevel)
end

function TPowerLevel.new(PowerLevel)
    return TPowerLevel_from_obj({PowerLevel = PowerLevel or [=[N/A]=]})
end
---@param obj EfficiencyCurve.PowerLevel
function TPowerLevel:init_from_obj(obj)
    self.PowerLevel = obj.PowerLevel or [=[N/A]=]
end

function TPowerLevel:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TPowerLevel.group)
end

TPowerLevel.from_obj = TPowerLevel_from_obj

TPowerLevel.proto_property = {'PowerLevel'}

TPowerLevel.default = {''}

TPowerLevel.struct = {{name = 'PowerLevel', is_array = false, struct = nil}}

function TPowerLevel:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'PowerLevel', self.PowerLevel, 'string', true, errs, need_convert)

    if self.PowerLevel ~= nil then
        validate.Enum(prefix .. 'PowerLevel', self.PowerLevel, '', {
            '80PLUS', '80PLUS Bronze', '80PLUS Silver', '80PLUS Gold', '80PLUS Platinum', '80PLUS Titanium', 'N/A'
        }, errs, need_convert)
    end

    TPowerLevel:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TPowerLevel.proto_property, errs, need_convert)
    return self
end

function TPowerLevel:unpack(_)
    return self.PowerLevel
end

EfficiencyCurve.PowerLevel = TPowerLevel

---@class EfficiencyCurve.EfficiencyCurveObject
---@field LoadPercent integer
---@field EfficiencyValue number
local TEfficiencyCurveObject = {}
TEfficiencyCurveObject.__index = TEfficiencyCurveObject
TEfficiencyCurveObject.group = {}

local function TEfficiencyCurveObject_from_obj(obj)
    return setmetatable(obj, TEfficiencyCurveObject)
end

function TEfficiencyCurveObject.new(LoadPercent, EfficiencyValue)
    return TEfficiencyCurveObject_from_obj({LoadPercent = LoadPercent, EfficiencyValue = EfficiencyValue})
end
---@param obj EfficiencyCurve.EfficiencyCurveObject
function TEfficiencyCurveObject:init_from_obj(obj)
    self.LoadPercent = obj.LoadPercent
    self.EfficiencyValue = obj.EfficiencyValue
end

function TEfficiencyCurveObject:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TEfficiencyCurveObject.group)
end

TEfficiencyCurveObject.from_obj = TEfficiencyCurveObject_from_obj

TEfficiencyCurveObject.proto_property = {'LoadPercent', 'EfficiencyValue'}

TEfficiencyCurveObject.default = {0, 0}

TEfficiencyCurveObject.struct = {
    {name = 'LoadPercent', is_array = false, struct = nil}, {name = 'EfficiencyValue', is_array = false, struct = nil}
}

function TEfficiencyCurveObject:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'LoadPercent', self.LoadPercent, 'uint8', true, errs, need_convert)
    validate.Optional(prefix .. 'EfficiencyValue', self.EfficiencyValue, 'double', true, errs, need_convert)

    TEfficiencyCurveObject:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TEfficiencyCurveObject.proto_property, errs, need_convert)
    return self
end

function TEfficiencyCurveObject:unpack(_)
    return self.LoadPercent, self.EfficiencyValue
end

EfficiencyCurve.EfficiencyCurveObject = TEfficiencyCurveObject

---@class EfficiencyCurve.EfficiencyCurve
---@field EfficiencyCurve EfficiencyCurve.EfficiencyCurveObject[]
local TEfficiencyCurve = {}
TEfficiencyCurve.__index = TEfficiencyCurve
TEfficiencyCurve.group = {}

local function TEfficiencyCurve_from_obj(obj)
    obj.EfficiencyCurve = utils.from_obj(EfficiencyCurve.EfficiencyCurveObject, obj.EfficiencyCurve, true)
    return setmetatable(obj, TEfficiencyCurve)
end

function TEfficiencyCurve.new(EfficiencyCurve)
    return TEfficiencyCurve_from_obj({EfficiencyCurve = EfficiencyCurve})
end
---@param obj EfficiencyCurve.EfficiencyCurve
function TEfficiencyCurve:init_from_obj(obj)
    self.EfficiencyCurve = obj.EfficiencyCurve
end

function TEfficiencyCurve:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TEfficiencyCurve.group)
end

TEfficiencyCurve.from_obj = TEfficiencyCurve_from_obj

TEfficiencyCurve.proto_property = {'EfficiencyCurve'}

TEfficiencyCurve.default = {{}}

TEfficiencyCurve.struct = {
    {name = 'EfficiencyCurve', is_array = true, struct = EfficiencyCurve.EfficiencyCurveObject.struct}
}

function TEfficiencyCurve:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    for _, v in pairs(self.EfficiencyCurve) do
        EfficiencyCurve.EfficiencyCurveObject.new(v.LoadPercent, v.EfficiencyValue):validate(prefix, errs, need_convert)
    end

    TEfficiencyCurve:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TEfficiencyCurve.proto_property, errs, need_convert)
    return self
end

function TEfficiencyCurve:unpack(raw)
    return utils.unpack(raw, self.EfficiencyCurve, true)
end

EfficiencyCurve.EfficiencyCurve = TEfficiencyCurve

EfficiencyCurve.interface = mdb.register_interface('bmc.kepler.Systems.PowerMgmt.OnePower.EfficiencyCurve', {
    EfficiencyCurve = {'a(yd)', {'CONST'}, true, nil},
    PowerLevel = {'s', {}, true, 'N/A'}
}, {}, {})

return EfficiencyCurve
